import Pen from "./lib/pen";
import Downloader from "./lib/downloader";
import WxCanvas from "./lib/wx-canvas";

const util = require("./lib/util");

const downloader = new Downloader();

// 最大尝试的绘制次数
const MAX_PAINT_COUNT = 5;
const ACTION_DEFAULT_SIZE = 24;
const ACTION_OFFSET = "2rpx";
Component({
    canvasWidthInPx: 0,
    canvasHeightInPx: 0,
    canvasNode: null,
    paintCount: 0,
    currentPalette: {},
    movingCache: {},
    outterDisabled: false,
    isDisabled: false,
    needClear: false,
    /**
   * 组件的属性列表
   */
    properties: {
        use2D: {
            type: Boolean,
        },
        customStyle: {
            type: String,
        },
        // 运行自定义选择框和删除缩放按钮
        customActionStyle: {
            type: Object,
        },
        palette: {
            type: Object,
            observer: function (newVal, oldVal) {
                if (this.isNeedRefresh(newVal, oldVal)) {
                    this.paintCount = 0;
                    this.startPaint();
                }
            },
        },
        dancePalette: {
            type: Object,
            observer: function (newVal, oldVal) {
                if (!this.isEmpty(newVal) && !this.properties.use2D) {
                    this.initDancePalette(newVal);
                }
            },
        },
        // 缩放比，会在传入的 palette 中统一乘以该缩放比
        scaleRatio: {
            type: Number,
            value: 1
        },
        widthPixels: {
            type: Number,
            value: 0
        },
        // 启用脏检查，默认 false
        dirty: {
            type: Boolean,
            value: false,
        },
        LRU: {
            type: Boolean,
            value: true,
        },
        action: {
            type: Object,
            observer: function (newVal, oldVal) {
                if (newVal && !this.isEmpty(newVal) && !this.properties.use2D) {
                    this.doAction(newVal, (callbackInfo) => {
                        this.movingCache = callbackInfo;
                    }, false, true);
                }
            },
        },
        disableAction: {
            type: Boolean,
            observer: function (isDisabled) {
                this.outterDisabled = isDisabled;
                this.isDisabled = isDisabled;
            }
        },
        clearActionBox: {
            type: Boolean,
            observer: function (needClear) {
                if (needClear && !this.needClear) {
                    if (this.frontContext) {
                        setTimeout(() => {
                            this.frontContext.draw();
                        }, 100);
                        this.touchedView = {};
                        this.prevFindedIndex = this.findedIndex;
                        this.findedIndex = -1;
                    }
                }
                this.needClear = needClear;
            }
        },
    },

    data: {
        picURL: "",
        showCanvas: true,
        painterStyle: "",
    },

    methods: {

        /**
     * 判断一个 object 是否为 空
     * @param {object} object
     */
        isEmpty(object) {
            for (const i in object) {
                return false;
            }
            return true;
        },

        isNeedRefresh(newVal, oldVal) {
            if (!newVal || this.isEmpty(newVal) || (this.data.dirty && util.equal(newVal, oldVal))) {
                return false;
            }
            return true;
        },

        getBox(rect, type) {
            const boxArea = {
                type: "rect",
                css: {
                    height: `${rect.bottom - rect.top}px`,
                    width: `${rect.right - rect.left}px`,
                    left: `${rect.left}px`,
                    top: `${rect.top}px`,
                    borderWidth: "4rpx",
                    borderColor: "#1A7AF8",
                    color: "transparent"
                }
            };
            if (type === "text") {
                boxArea.css = Object.assign({}, boxArea.css, {
                    borderStyle: "dashed"
                });
            }
            if (this.properties.customActionStyle && this.properties.customActionStyle.border) {
                boxArea.css = Object.assign({}, boxArea.css, this.properties.customActionStyle.border);
            }
            Object.assign(boxArea, {
                id: "box"
            });
            return boxArea;
        },

        getScaleIcon(rect, type) {
            let scaleArea = {};
            const {
                customActionStyle
            } = this.properties;
            if (customActionStyle && customActionStyle.scale) {
                scaleArea = {
                    type: "image",
                    url: type === "text" ? customActionStyle.scale.textIcon : customActionStyle.scale.imageIcon,
                    css: {
                        height: `${2 * ACTION_DEFAULT_SIZE}rpx`,
                        width: `${2 * ACTION_DEFAULT_SIZE}rpx`,
                        borderRadius: `${ACTION_DEFAULT_SIZE}rpx`,
                    }
                };
            } else {
                scaleArea = {
                    type: "rect",
                    css: {
                        height: `${2 * ACTION_DEFAULT_SIZE}rpx`,
                        width: `${2 * ACTION_DEFAULT_SIZE}rpx`,
                        borderRadius: `${ACTION_DEFAULT_SIZE}rpx`,
                        color: "#0000ff",
                    }
                };
            }
            scaleArea.css = Object.assign({}, scaleArea.css, {
                align: "center",
                left: `${rect.right + ACTION_OFFSET.toPx()}px`,
                top: type === "text" ? `${rect.top - ACTION_OFFSET.toPx() - scaleArea.css.height.toPx() / 2}px` : `${rect.bottom - ACTION_OFFSET.toPx() - scaleArea.css.height.toPx() / 2}px`
            });
            Object.assign(scaleArea, {
                id: "scale"
            });
            return scaleArea;
        },

        getDeleteIcon(rect) {
            let deleteArea = {};
            const {
                customActionStyle
            } = this.properties;
            if (customActionStyle && customActionStyle.scale) {
                deleteArea = {
                    type: "image",
                    url: customActionStyle.delete.icon,
                    css: {
                        height: `${2 * ACTION_DEFAULT_SIZE}rpx`,
                        width: `${2 * ACTION_DEFAULT_SIZE}rpx`,
                        borderRadius: `${ACTION_DEFAULT_SIZE}rpx`,
                    }
                };
            } else {
                deleteArea = {
                    type: "rect",
                    css: {
                        height: `${2 * ACTION_DEFAULT_SIZE}rpx`,
                        width: `${2 * ACTION_DEFAULT_SIZE}rpx`,
                        borderRadius: `${ACTION_DEFAULT_SIZE}rpx`,
                        color: "#0000ff",
                    }
                };
            }
            deleteArea.css = Object.assign({}, deleteArea.css, {
                align: "center",
                left: `${rect.left - ACTION_OFFSET.toPx()}px`,
                top: `${rect.top - ACTION_OFFSET.toPx() - deleteArea.css.height.toPx() / 2}px`
            });
            Object.assign(deleteArea, {
                id: "delete"
            });
            return deleteArea;
        },

        doAction(action, callback, isMoving, overwrite) {
            if (this.properties.use2D) {
                return;
            }
            let newVal = null;
            if (action) {
                newVal = action.view;
            }
            if (newVal && newVal.id && this.touchedView.id !== newVal.id) {
                // 带 id 的动作给撤回时使用，不带 id，表示对当前选中对象进行操作
                const {
                    views
                } = this.currentPalette;
                for (let i = 0; i < views.length; i++) {
                    if (views[i].id === newVal.id) {
                        // 跨层回撤，需要重新构建三层关系
                        this.touchedView = views[i];
                        this.findedIndex = i;
                        this.sliceLayers();
                        break;
                    }
                }
            }

            const doView = this.touchedView;

            if (!doView || this.isEmpty(doView)) {
                return;
            }
            if (newVal && newVal.css) {
                if (overwrite) {
                    doView.css = newVal.css;
                } else if (Array.isArray(doView.css) && Array.isArray(newVal.css)) {
                    doView.css = Object.assign({}, ...doView.css, ...newVal.css);
                } else if (Array.isArray(doView.css)) {
                    doView.css = Object.assign({}, ...doView.css, newVal.css);
                } else if (Array.isArray(newVal.css)) {
                    doView.css = Object.assign({}, doView.css, ...newVal.css);
                } else {
                    doView.css = Object.assign({}, doView.css, newVal.css);
                }
            }
            if (newVal && newVal.rect) {
                doView.rect = newVal.rect;
            }
            if (newVal && newVal.url && doView.url && newVal.url !== doView.url) {
                downloader.download(newVal.url, this.properties.LRU).then((path) => {
                    if (newVal.url.startsWith("https")) {
                        doView.originUrl = newVal.url;
                    }
                    doView.url = path;
                    wx.getImageInfo({
                        src: path,
                        success: (res) => {
                            doView.sHeight = res.height;
                            doView.sWidth = res.width;
                            this.reDraw(doView, callback, isMoving);
                        },
                        fail: () => {
                            this.reDraw(doView, callback, isMoving);
                        }
                    });
                }).catch((error) => {
                    // 未下载成功，直接绘制
                    console.error(error);
                    this.reDraw(doView, callback, isMoving);
                });
            } else {
                (newVal && newVal.text && doView.text && newVal.text !== doView.text) && (doView.text = newVal.text);
                (newVal && newVal.content && doView.content && newVal.content !== doView.content) && (doView.content = newVal.content);
                this.reDraw(doView, callback, isMoving);
            }
        },

        reDraw(doView, callback, isMoving) {
            const draw = {
                width: this.currentPalette.width,
                height: this.currentPalette.height,
                views: this.isEmpty(doView) ? [] : [doView]
            };
            const pen = new Pen(this.globalContext, draw);

            if (isMoving && doView.type === "text") {
                pen.paint((callbackInfo) => {
                    callback && callback(callbackInfo);
                    this.triggerEvent("viewUpdate", {
                        view: this.touchedView
                    });
                }, true, this.movingCache);
            } else {
                // 某些机型（华为 P20）非移动和缩放场景下，只绘制一遍会偶然性图片绘制失败
                // if (!isMoving && !this.isScale) {
                //   pen.paint()
                // }
                pen.paint((callbackInfo) => {
                    callback && callback(callbackInfo);
                    this.triggerEvent("viewUpdate", {
                        view: this.touchedView
                    });
                });
            }

            const {
                rect,
                css,
                type
            } = doView;

            this.block = {
                width: this.currentPalette.width,
                height: this.currentPalette.height,
                views: this.isEmpty(doView) ? [] : [this.getBox(rect, doView.type)]
            };
            if (css && css.scalable) {
                this.block.views.push(this.getScaleIcon(rect, type));
            }
            if (css && css.deletable) {
                this.block.views.push(this.getDeleteIcon(rect));
            }
            const topBlock = new Pen(this.frontContext, this.block);
            topBlock.paint();
        },

        isInView(x, y, rect) {
            return (x > rect.left &&
        y > rect.top &&
        x < rect.right &&
        y < rect.bottom
            );
        },

        isInDelete(x, y) {
            for (const view of this.block.views) {
                if (view.id === "delete") {
                    return (x > view.rect.left &&
            y > view.rect.top &&
            x < view.rect.right &&
            y < view.rect.bottom);
                }
            }
            return false;
        },

        isInScale(x, y) {
            for (const view of this.block.views) {
                if (view.id === "scale") {
                    return (x > view.rect.left &&
            y > view.rect.top &&
            x < view.rect.right &&
            y < view.rect.bottom);
                }
            }
            return false;
        },

        touchedView: {},
        findedIndex: -1,
        onClick() {
            const x = this.startX;
            const y = this.startY;
            const totalLayerCount = this.currentPalette.views.length;
            let canBeTouched = [];
            let isDelete = false;
            let deleteIndex = -1;
            for (let i = totalLayerCount - 1; i >= 0; i--) {
                const view = this.currentPalette.views[i];
                const {
                    rect
                } = view;
                if (this.touchedView && this.touchedView.id && this.touchedView.id === view.id && this.isInDelete(x, y, rect)) {
                    canBeTouched.length = 0;
                    deleteIndex = i;
                    isDelete = true;
                    break;
                }
                if (this.isInView(x, y, rect)) {
                    canBeTouched.push({
                        view,
                        index: i
                    });
                }
            }
            this.touchedView = {};
            if (canBeTouched.length === 0) {
                this.findedIndex = -1;
            } else {
                let i = 0;
                const touchAble = canBeTouched.filter(item => Boolean(item.view.id));
                if (touchAble.length === 0) {
                    this.findedIndex = canBeTouched[0].index;
                } else {
                    for (i = 0; i < touchAble.length; i++) {
                        if (this.findedIndex === touchAble[i].index) {
                            i++;
                            break;
                        }
                    }
                    if (i === touchAble.length) {
                        i = 0;
                    }
                    this.touchedView = touchAble[i].view;
                    this.findedIndex = touchAble[i].index;
                    this.triggerEvent("viewClicked", {
                        view: this.touchedView
                    });
                }
            }
            if (this.findedIndex < 0 || (this.touchedView && !this.touchedView.id)) {
                // 证明点击了背景 或无法移动的view
                this.frontContext.draw();
                if (isDelete) {
                    this.triggerEvent("touchEnd", {
                        view: this.currentPalette.views[deleteIndex],
                        index: deleteIndex,
                        type: "delete"
                    });
                    this.doAction();
                } else if (this.findedIndex < 0) {
                    this.triggerEvent("viewClicked", {});
                }
                this.findedIndex = -1;
                this.prevFindedIndex = -1;
            } else if (this.touchedView && this.touchedView.id) {
                this.sliceLayers();
            }
        },

        sliceLayers() {
            const bottomLayers = this.currentPalette.views.slice(0, this.findedIndex);
            const topLayers = this.currentPalette.views.slice(this.findedIndex + 1);
            const bottomDraw = {
                width: this.currentPalette.width,
                height: this.currentPalette.height,
                background: this.currentPalette.background,
                views: bottomLayers
            };
            const topDraw = {
                width: this.currentPalette.width,
                height: this.currentPalette.height,
                views: topLayers
            };
            if (this.prevFindedIndex < this.findedIndex) {
                new Pen(this.bottomContext, bottomDraw).paint();
                this.doAction(null, (callbackInfo) => {
                    this.movingCache = callbackInfo;
                });
                new Pen(this.topContext, topDraw).paint();
            } else {
                new Pen(this.topContext, topDraw).paint();
                this.doAction(null, (callbackInfo) => {
                    this.movingCache = callbackInfo;
                });
                new Pen(this.bottomContext, bottomDraw).paint();
            }
            this.prevFindedIndex = this.findedIndex;
        },

        startX: 0,
        startY: 0,
        startH: 0,
        startW: 0,
        isScale: false,
        startTimeStamp: 0,
        onTouchStart(event) {
            if (this.isDisabled) {
                return;
            }
            const {
                x,
                y
            } = event.touches[0];
            this.startX = x;
            this.startY = y;
            this.startTimeStamp = new Date().getTime();
            if (this.touchedView && !this.isEmpty(this.touchedView)) {
                const {
                    rect
                } = this.touchedView;
                if (this.isInScale(x, y, rect)) {
                    this.isScale = true;
                    this.movingCache = {};
                    this.startH = rect.bottom - rect.top;
                    this.startW = rect.right - rect.left;
                } else {
                    this.isScale = false;
                }
            } else {
                this.isScale = false;
            }
        },

        onTouchEnd(e) {
            if (this.isDisabled) {
                return;
            }
            const current = new Date().getTime();
            if ((current - this.startTimeStamp) <= 500 && !this.hasMove) {
                !this.isScale && this.onClick(e);
            } else if (this.touchedView && !this.isEmpty(this.touchedView)) {
                this.triggerEvent("touchEnd", {
                    view: this.touchedView,
                });
            }
            this.hasMove = false;
        },

        onTouchCancel(e) {
            if (this.isDisabled) {
                return;
            }
            this.onTouchEnd(e);
        },

        hasMove: false,
        onTouchMove(event) {
            if (this.isDisabled) {
                return;
            }
            this.hasMove = true;
            if (!this.touchedView || (this.touchedView && !this.touchedView.id)) {
                return;
            }
            const {
                x,
                y
            } = event.touches[0];
            const offsetX = x - this.startX;
            const offsetY = y - this.startY;
            const {
                rect,
                type
            } = this.touchedView;
            let css = {};
            if (this.isScale) {
                const newW = this.startW + offsetX > 1 ? this.startW + offsetX : 1;
                if (this.touchedView.css && this.touchedView.css.minWidth) {
                    if (newW < this.touchedView.css.minWidth.toPx()) {
                        return;
                    }
                }
                if (this.touchedView.rect && this.touchedView.rect.minWidth) {
                    if (newW < this.touchedView.rect.minWidth) {
                        return;
                    }
                }
                const newH = this.startH + offsetY > 1 ? this.startH + offsetY : 1;
                css = {
                    width: `${newW}px`,
                };
                if (type !== "text") {
                    if (type === "image") {
                        css.height = `${(newW) * this.startH / this.startW }px`;
                    } else {
                        css.height = `${newH}px`;
                    }
                }
            } else {
                this.startX = x;
                this.startY = y;
                css = {
                    left: `${rect.x + offsetX}px`,
                    top: `${rect.y + offsetY}px`,
                    right: undefined,
                    bottom: undefined
                };
            }
            this.doAction({
                view: {
                    css
                }
            }, (callbackInfo) => {
                if (this.isScale) {
                    this.movingCache = callbackInfo;
                }
            }, !this.isScale);
        },

        initScreenK() {
            if (!(getApp() && getApp().systemInfo && getApp().systemInfo.screenWidth)) {
                try {
                    getApp().systemInfo = wx.getSystemInfoSync();
                } catch (e) {
                    console.error(`Painter get system info failed, ${JSON.stringify(e)}`);
                    return;
                }
            }
            this.screenK = 0.5;
            if (getApp() && getApp().systemInfo && getApp().systemInfo.screenWidth) {
                this.screenK = getApp().systemInfo.screenWidth / 750;
            }
            setStringPrototype(this.screenK, this.properties.scaleRatio);
        },

        initDancePalette() {
            if (this.properties.use2D) {
                return;
            }
            this.isDisabled = true;
            this.initScreenK();
            this.downloadImages(this.properties.dancePalette).then(async (palette) => {
                this.currentPalette = palette;
                const {
                    width,
                    height
                } = palette;

                if (!width || !height) {
                    console.error(`You should set width and height correctly for painter, width: ${width}, height: ${height}`);
                    return;
                }
                this.setData({
                    painterStyle: `width:${width.toPx()}px;height:${height.toPx()}px;`,
                });
                this.frontContext || (this.frontContext = await this.getCanvasContext(this.properties.use2D, "front"));
                this.bottomContext || (this.bottomContext = await this.getCanvasContext(this.properties.use2D, "bottom"));
                this.topContext || (this.topContext = await this.getCanvasContext(this.properties.use2D, "top"));
                this.globalContext || (this.globalContext = await this.getCanvasContext(this.properties.use2D, "k-canvas"));
                new Pen(this.bottomContext, palette, this.properties.use2D).paint(() => {
                    this.isDisabled = false;
                    this.isDisabled = this.outterDisabled;
                    this.triggerEvent("didShow");
                });
                this.globalContext.draw();
                this.frontContext.draw();
                this.topContext.draw();
            });
            this.touchedView = {};
        },

        startPaint() {
            this.initScreenK();

            this.downloadImages(this.properties.palette).then(async (palette) => {
                const {
                    width,
                    height
                } = palette;

                if (!width || !height) {
                    console.error(`You should set width and height correctly for painter, width: ${width}, height: ${height}`);
                    return;
                }

                let needScale = false;
                // 生成图片时，根据设置的像素值重新绘制
                if (width.toPx() !== this.canvasWidthInPx) {
                    this.canvasWidthInPx = width.toPx();
                    needScale = this.properties.use2D;
                }
                if (this.properties.widthPixels) {
                    setStringPrototype(this.screenK, this.properties.widthPixels / this.canvasWidthInPx);
                    this.canvasWidthInPx = this.properties.widthPixels;
                }

                if (this.canvasHeightInPx !== height.toPx()) {
                    this.canvasHeightInPx = height.toPx();
                    needScale = needScale || this.properties.use2D;
                }
                this.setData({
                    photoStyle: `width:${this.canvasWidthInPx}px;height:${this.canvasHeightInPx}px;`,
                });
                if (!this.photoContext) {
                    this.photoContext = await this.getCanvasContext(this.properties.use2D, "photo");
                }
                if (needScale) {
                    const scale = getApp().systemInfo.pixelRatio;
                    this.photoContext.width = this.canvasWidthInPx * scale;
                    this.photoContext.height = this.canvasHeightInPx * scale;
                    this.photoContext.scale(scale, scale);
                }
                new Pen(this.photoContext, palette).paint(() => {
                    this.saveImgToLocal();
                });
                setStringPrototype(this.screenK, this.properties.scaleRatio);
            });
        },

        downloadImages(palette) {
            return new Promise((resolve, reject) => {
                let preCount = 0;
                let completeCount = 0;
                const paletteCopy = JSON.parse(JSON.stringify(palette));
                if (paletteCopy.background) {
                    preCount++;
                    downloader.download(paletteCopy.background, this.properties.LRU).then((path) => {
                        paletteCopy.background = path;
                        completeCount++;
                        if (preCount === completeCount) {
                            resolve(paletteCopy);
                        }
                    }, () => {
                        completeCount++;
                        if (preCount === completeCount) {
                            resolve(paletteCopy);
                        }
                    });
                }
                if (paletteCopy.views) {
                    for (const view of paletteCopy.views) {
                        if (view && view.type === "image" && view.url) {
                            preCount++;
                            /* eslint-disable no-loop-func */
                            downloader.download(view.url, this.properties.LRU).then((path) => {
                                view.originUrl = view.url;
                                view.url = path;
                                wx.getImageInfo({
                                    src: path,
                                    success: (res) => {
                                        // 获得一下图片信息，供后续裁减使用
                                        view.sWidth = res.width;
                                        view.sHeight = res.height;
                                    },
                                    fail: (error) => {
                                        // 如果图片坏了，则直接置空，防止坑爹的 canvas 画崩溃了
                                        console.warn(`getImageInfo ${view.originUrl} failed, ${JSON.stringify(error)}`);
                                        view.url = "";
                                    },
                                    complete: () => {
                                        completeCount++;
                                        if (preCount === completeCount) {
                                            resolve(paletteCopy);
                                        }
                                    },
                                });
                            }, () => {
                                completeCount++;
                                if (preCount === completeCount) {
                                    resolve(paletteCopy);
                                }
                            });
                        }
                    }
                }
                if (preCount === 0) {
                    resolve(paletteCopy);
                }
            });
        },

        saveImgToLocal() {
            const that = this;
            setTimeout(() => {
                wx.canvasToTempFilePath({
                    canvasId: "photo",
                    canvas: that.properties.use2D ? that.canvasNode : null,
                    destWidth: that.canvasWidthInPx * getApp().systemInfo.pixelRatio,
                    destHeight: that.canvasHeightInPx * getApp().systemInfo.pixelRatio,
                    success: function (res) {
                        that.getImageInfo(res.tempFilePath);
                    },
                    fail: function (error) {
                        console.error(`canvasToTempFilePath failed, ${JSON.stringify(error)}`);
                        that.triggerEvent("imgErr", {
                            error: error
                        });
                    },
                }, this);
            }, 300);
        },


        getCanvasContext(use2D, id) {
            const that = this;
            return new Promise(resolve => {
                if (use2D) {
                    const query = wx.createSelectorQuery().in(that);
                    const selectId = `#${id}`;
                    query.select(selectId)
                        .fields({ node: true, size: true })
                        .exec((res) => {
                            that.canvasNode = res[0].node;
                            const ctx = that.canvasNode.getContext("2d");
                            const wxCanvas = new WxCanvas("2d", ctx, id, true, that.canvasNode);
                            resolve(wxCanvas);
                        });
                } else {
                    const temp = wx.createCanvasContext(id, that);
                    resolve(new WxCanvas("mina", temp, id, true));
                }
            });
        },

        getImageInfo(filePath) {
            const that = this;
            wx.getImageInfo({
                src: filePath,
                success: (infoRes) => {
                    if (that.paintCount > MAX_PAINT_COUNT) {
                        const error = `The result is always fault, even we tried ${MAX_PAINT_COUNT} times`;
                        console.error(error);
                        that.triggerEvent("imgErr", {
                            error: error
                        });
                        return;
                    }
                    // 比例相符时才证明绘制成功，否则进行强制重绘制
                    if (Math.abs((infoRes.width * that.canvasHeightInPx - that.canvasWidthInPx * infoRes.height) / (infoRes.height * that.canvasHeightInPx)) < 0.01) {
                        that.triggerEvent("imgOK", {
                            path: filePath
                        });
                    } else {
                        that.startPaint();
                    }
                    that.paintCount++;
                },
                fail: (error) => {
                    console.error(`getImageInfo failed, ${JSON.stringify(error)}`);
                    that.triggerEvent("imgErr", {
                        error: error
                    });
                },
            });
        },
    },
});


function setStringPrototype(screenK, scale) {
    /* eslint-disable no-extend-native */
    /**
   * 是否支持负数
   * @param {Boolean} minus 是否支持负数
   * @param {Number} baseSize 当设置了 % 号时，设置的基准值
   */
    String.prototype.toPx = function toPx(minus, baseSize) {
        if (this === "0") {
            return 0;
        }
        let reg;
        if (minus) {
            reg = /^-?[0-9]+([.]{1}[0-9]+){0,1}(rpx|px|%)$/g;
        } else {
            reg = /^[0-9]+([.]{1}[0-9]+){0,1}(rpx|px|%)$/g;
        }
        const results = reg.exec(this);
        if (!this || !results) {
            console.error(`The size: ${this} is illegal`);
            return 0;
        }
        const unit = results[2];
        const value = parseFloat(this);

        let res = 0;
        if (unit === "rpx") {
            res = Math.round(value * (screenK || 0.5) * (scale || 1));
        } else if (unit === "px") {
            res = Math.round(value * (scale || 1));
        } else if (unit === "%") {
            res = Math.round(value * baseSize / 100);
        }
        return res;
    };
}